/*//获取单例对象，并设置默认的页面编码
 public static HttpClientUtil getInstance(String urlCharset);

 //设置编码
 public void setUrlCharset(String urlCharset);

 //获取字符串型返回结果，通过发起http post请求
 public String getResponseBodyAsString(String targetUrl,Map params)throws Exception;

 //获取字符数组型返回结果，通过发起http post请求
 public byte[] getResponseBodyAsByteArray(String targetUrl,Map params)throws Exception;

 //将response的返回流写到outputStream中，通过发起http post请求
 public void getResponseBodyAsStream(String targetUrl,Map params,OutputStream outputStream)throws Exception;*/

/*
 * 创建日期 2014-3-13
 *
 * TODO 要更改此生成的文件的模板，请转至
 * 窗口 － 首选项 － Java － 代码样式 － 代码模板
 */
package com.babel.util.http;

import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.imageio.ImageIO;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author administrator
 *
 *         Http Client工具类 发起http client 请求
 * 
 *         窗口 － 首选项 － Java － 代码样式 － 代码模板
 */
public final class HttpClientUtil {

	private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

	private static final String TYPE_STRING = "string";

	private static final String TYPE_BYTEARRAY = "byte[]";

	private static final String TYPE_STREAM = "stream";

	public static final String CONTENT_TYPE_STREAM = "application/octet-stream";

	public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";

	private static HttpClientUtil instance;

	private HttpClientUtil() {
	}

	/**
	 * 使用默认的页面请求编码：utf-8
	 * 
	 * @return
	 */
	public static HttpClientUtil getInstance() {
		return getInstance("UTF-8");
	}

	public static HttpClientUtil getInstance(String urlCharset) {
		if (instance == null) {
			instance = new HttpClientUtil();
		}
		// 设置默认的url编码
		instance.setUrlCharset(urlCharset);
		return instance;
	}

	/**
	 * 请求编码，默认使用utf-8
	 */
	private String urlCharset = "UTF-8";

	/**
	 * @param urlCharset
	 *            要设置的 urlCharset。
	 */
	public void setUrlCharset(String urlCharset) {
		this.urlCharset = urlCharset;
	}

	/**
	 * 获取字符串型返回结果，通过发起http post请求
	 * 
	 * @param targetUrl
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public String getResponseBodyAsString(String targetUrl, Map<String, String> params) throws Exception {

		return (String) setPostRequest(targetUrl, params, TYPE_STRING, null);
	}

	/**
	 * 获取字符数组型返回结果，通过发起http post请求
	 * 
	 * @param targetUrl
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public byte[] getResponseBodyAsByteArray(String targetUrl, Map<String, String> params) throws Exception {

		return (byte[]) setPostRequest(targetUrl, params, TYPE_BYTEARRAY, null);
	}

	/**
	 * 将response的返回流写到outputStream中，通过发起http post请求
	 * 
	 * @param targetUrl
	 *            请求地址
	 * @param params
	 *            请求参数<paramName,paramValue>
	 * @param outputStream
	 *            输出流
	 * @throws Exception
	 */
	public void getResponseBodyAsStream(String targetUrl, Map<String, String> params, OutputStream outputStream) throws Exception {
		if (outputStream == null) {
			throw new IllegalArgumentException("调用HttpClientUtil.setPostRequest方法，targetUrl不能为空!");
		}

		// response 的返回结果写到输出流
		setPostRequest(targetUrl, params, TYPE_STREAM, outputStream);
	}

	/**
	 * 利用http client模拟发送http post请求
	 * 
	 * @param targetUrl
	 *            请求地址
	 * @param params
	 *            请求参数<paramName,paramValue>
	 * @return Object 返回的类型可能是：String 或者 byte[] 或者 outputStream
	 * @throws Exception
	 */
	private Object setPostRequest(String targetUrl, Map<String, String> params, String responseType, OutputStream outputStream) throws Exception {
		if (StringUtils.isBlank(targetUrl)) {
			throw new IllegalArgumentException("调用HttpClientUtil.setPostRequest方法，targetUrl不能为空!");
		}

		Object responseResult = null;
		HttpClient client = null;
		PostMethod post = null;
		NameValuePair[] nameValuePairArr = null;
		SimpleHttpConnectionManager connectionManager = null;
		try {
			connectionManager = new SimpleHttpConnectionManager(true);
			// 连接超时,单位毫秒
			connectionManager.getParams().setConnectionTimeout(3000);
			// 读取超时,单位毫秒
			connectionManager.getParams().setSoTimeout(60000);

			// 设置获取内容编码
			connectionManager.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, urlCharset);
			client = new HttpClient(new HttpClientParams(), connectionManager);

			post = new PostMethod(targetUrl);
			// 设置请求参数的编码
			post.getParams().setContentCharset(urlCharset);

			// 服务端完成返回后，主动关闭链接
			post.setRequestHeader("Connection", "close");
			if (params != null) {
				nameValuePairArr = new NameValuePair[params.size()];

				Set<String> key = params.keySet();
				Iterator<String> keyIte = key.iterator();
				int index = 0;
				while (keyIte.hasNext()) {
					Object paramName = keyIte.next();
					Object paramValue = params.get(paramName);
					if (paramName instanceof String && paramValue instanceof String) {
						NameValuePair pair = new NameValuePair((String) paramName, (String) paramValue);
						nameValuePairArr[index] = pair;
						index++;
					}
				}

				post.addParameters(nameValuePairArr);
			}

			int sendStatus = client.executeMethod(post);

			if (sendStatus == HttpStatus.SC_OK) {
				System.out.println("HttpClientUtil.setPostRequest()-responseType:" + responseType);

				if (StringUtils.equals(TYPE_STRING, responseType)) {
					responseResult = post.getResponseBodyAsString();
				} else if (StringUtils.equals(TYPE_BYTEARRAY, responseType)) {
					responseResult = post.getResponseBody();
				} else if (StringUtils.equals(TYPE_STREAM, responseType)) {
					InputStream tempStream = post.getResponseBodyAsStream();
					byte[] temp = new byte[1024];
					while ((tempStream.read(temp)) != -1) {
						outputStream.write(temp);
					}
				}
			} else {
				System.err.println("***************************");
				System.err.println("HttpClientUtil.setPostRequest()-请求url：" + targetUrl);
				// +" 出错\n请求参数有："+JsonUtil.java2JsonStr(params)+"！！！"
				System.err.println("***************************");
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 释放链接
			if (post != null) {
				post.releaseConnection();
			}

			// 关闭链接
			if (connectionManager != null) {
				connectionManager.shutdown();
			}
		}

		return responseResult;
	}

	/**
	 * 组装请求url
	 *
	 * @param map
	 * @return
	 */
	public static String getEncodeParent(LinkedHashMap<String, Object> map) {
		StringBuffer params = new StringBuffer();// 请求url
		Iterator<String> it = map.keySet().iterator();
		while (it.hasNext()) {
			String key = it.next();
			try {
				String encode = URLEncoder.encode((String) map.get(key), "utf-8");
				params.append(key + "=" + encode + "&");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		return params.toString().substring(0, params.toString().length() - 1);
	}
	
	
	
	
	/**
	 * 组装请求url
	 * 
	 * @param map
	 * @return
	 */
	public static String getParent(LinkedHashMap<String, Object> map) {
		StringBuffer params = new StringBuffer();// 请求url
		Iterator<String> it = map.keySet().iterator();
		while (it.hasNext()) {
			String key = it.next();
			params.append(key + "=" + map.get(key) + "&");
		}
		return params.toString().substring(0, params.toString().length() - 1);
	}
	
	/**
	 * 向指定URL发送GET方法的请求
	 * 
	 * @param url
	 *            发送请求的URL
	 * @param param
	 *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return URL 所代表远程资源的响应结果
	 */
	public static String sendGet(String url, String param) {
		String urlNameString = url + "?" + param;
		return sendGet(urlNameString);
	}

	/**
	 * 向指定URL发送GET方法的请求
	 * 
	 * @param url
	 *            发送请求的URL
	 * @param map
	 *            请求参数
	 * @return URL 所代表远程资源的响应结果
	 */
	public static String sendGet(String url, LinkedHashMap<String, Object> map) {
		return sendGet(url + "?" + getParent(map));
	}

	/**
	 * 向指定URL发送GET方法的请求
	 * 
	 * @param url
	 *            发送请求的URL
	 * @return URL 所代表远程资源的响应结果
	 */
	public static String sendGet(String uri) {
		String result = "";
		BufferedReader in = null;
		try {
			URL realUrl = new URL(uri);
			// 打开和URL之间的连接
			URLConnection connection = realUrl.openConnection();
			// 设置通用的请求属性
			connection.setRequestProperty("accept", "*/*");
			connection.setRequestProperty("connection", "Keep-Alive");
			connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 建立实际的连接
			connection.connect();
			// 获取所有响应头字段
			Map<String, List<String>> map = connection.getHeaderFields();
			// 遍历所有的响应头字段
			/*for (String key : map.keySet()) {
				System.out.println(key + "--->" + map.get(key));
			}*/
			// 定义 BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送GET请求出现异常！" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输入流
		finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return result;
	}
	
	/**
	 * 向指定 URL 发送POST方法的请求
	 * 
	 * @param url
	 *            发送请求的 URL
	 * @param param
	 *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, String param) {
		return sendPost(url, param, null);
	}
	
	/**
	 * 向指定 URL 发送POST方法的请求
	 * 
	 * @param url
	 *            发送请求的 URL
	 * @param map
	 *            请求参数
	 * @param charset
	 *            字符集
	 * 
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, LinkedHashMap<String, Object> map) {
		return sendPost(url, getParent(map));
	}
	public static String sendPost(String url, LinkedHashMap<String, Object> map, String ContentType) {
		return sendPost(url, getParent(map), ContentType);
	}

	/**
	 * 向指定 URL 发送POST方法的请求
	 * 
	 * @param url
	 *            发送请求的 URL
	 * @param param
	 *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, String param, String ContentType) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		ContentType = ContentType==null?"application/json":ContentType;
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestMethod("POST");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("Content-Type", ContentType);
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setConnectTimeout(3000);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(param);
			// flush输出流的缓冲
			out.flush();
			out.close();

			int code = conn.getResponseCode();
			if (code==200) {
				// 定义BufferedReader输入流来读取URL的响应
				in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
				String line;
				while ((line = in.readLine()) != null) {
					result += line;
				}
			} else {
				StringBuffer error = new StringBuffer();
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
				String line1 = null;
				while ((line1 = bufferedReader.readLine()) != null) {
					error.append(line1).append("\n");
				}
				result = error.toString();
				bufferedReader.close();
				bufferedReader = null;
			}
		} catch (Exception e) {
			logger.error("发送 POST 请求出现异常！" + e);
			throw new RuntimeException("发送 POST 请求出现异常！",e);
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 上传图片
	 * fileMap中key为属性名称	 value为文件的网络地址（fastDFS全路径地址）
	 */
	public static String sendPost(String urlStr, Map<String, String> textMap,
									Map<String, String> fileMap, String contentType) {
		String res = "";
		HttpURLConnection conn = null;
		String BOUNDARY = "---------------------------123821742118716";
		try {
			URL url = new URL(urlStr);
			conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setReadTimeout(30000);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Connection", "close");
			conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
			conn.setRequestProperty("Content-Type","multipart/form-data; boundary=" + BOUNDARY);
			conn.setRequestProperty("Charset", "UTF-8");
			OutputStream out = new DataOutputStream(conn.getOutputStream());
			if (textMap != null) {
				StringBuilder sb = new StringBuilder();
				Iterator iter = textMap.entrySet().iterator();
				while (iter.hasNext()) {
					Map.Entry entry = (Map.Entry) iter.next();
					String inputName = (String) entry.getKey();
					String inputValue = (String) entry.getValue();
					if (inputValue == null) {
						continue;
					}
					sb.append("\r\n").append("--").append(BOUNDARY).append("\r\n")
							.append("Content-Disposition: form-data; name=\"").append(inputName).append("\"\r\n\r\n")
							.append(inputValue);
				}
				out.write(sb.toString().getBytes());
			}
			if (fileMap != null) {
				for (String inputName : fileMap.keySet()) {
					String inputValue = fileMap.get(inputName);
					if (inputValue == null) {
						continue;
					}
					String[] strArray = inputValue.split("/");
					String filename = strArray[strArray.length - 1];
					HttpURLConnection uc = (HttpURLConnection) new URL(inputValue).openConnection();
					uc.setDoInput(true);//设置是否要从 URL 连接读取数据,默认为true
					uc.connect();
					InputStream fileInputStream = uc.getInputStream();

					String strBuf = "\r\n" +
							"--" +
							BOUNDARY +
							"\r\n" +
							"Content-Disposition: form-data; name=\"" +
							inputName +
							"\"; filename=\"" +
							filename +
							"\"\r\n" +
							"Content-Type:" + contentType + "\r\n\r\n";
					out.write(strBuf.getBytes());
					int bytes = 0;
					byte[] bufferOut = new byte[1024];
					while ((bytes = fileInputStream.read(bufferOut)) != -1) {
						out.write(bufferOut, 0, bytes);
					}
					fileInputStream.close();
				}
			}
			byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
			out.write(endData);
			out.flush();
			out.close();
			int responseCode = conn.getResponseCode();
			if (responseCode == 200) {
				// 读取返回数据
				StringBuffer strBuf = new StringBuffer();
				BufferedReader reader = new BufferedReader(new InputStreamReader(
						conn.getInputStream()));

				String line = null;
				while ((line = reader.readLine()) != null) {
					strBuf.append(line).append("\n");
				}
				res = strBuf.toString();
				reader.close();
				reader = null;
			} else {
				StringBuffer error = new StringBuffer();
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
						conn.getErrorStream()));
				String line1 = null;
				while ((line1 = bufferedReader.readLine()) != null) {
					error.append(line1).append("\n");
				}
				res = error.toString();
				logger.error(res);
				bufferedReader.close();
				bufferedReader = null;
			}

		} catch (Exception e) {
			System.out.println("发送POST请求出错。" + e);
			logger.error("发送POST请求出错",e);
			e.printStackTrace();
		} finally {
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
		}
		return res;
	}
	
	/**
	 * 请求获取图片， 只支持get请求
	 * @param urlStr
	 * @param request
	 * @return
	 */
	public static BufferedImage downloadImage(String urlStr){
		URL url = null;              
		HttpURLConnection httpConn = null;  
		BufferedImage image = null;
		try{     
			url = new URL(urlStr);  
			httpConn = (HttpURLConnection) url.openConnection();  
			InputStream inputStream = httpConn.getInputStream();
			image = ImageIO.read(inputStream);
		} catch (Exception ex) {   

		} finally{   
			httpConn.disconnect();
		}       
		return image;
	}

	/**
	 * 测试方法
	 * 
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		HttpClientUtil.sendPost("localhost:9080/platform/baseService/um/dataSync.do", "{username:\"admin\",password:\"123456\"}",null);
		/*
		 * 
		 * //String url =
		 * "http://192.168.33.33:7001/rworg/rworg/poPublic.do?method=portalSearch"
		 * ; String url =http://192.168.3.36:8081/mgmt/sendloginsms
		 * "http://localhost:9080/platform/baseService/um/dataSync.do"; Map
		 * params = new HashMap(); params.put("method","saveUser");
		 * params.put("userAccount","admin"); params.put("keyWords","111");
		 * params.put("type","中午 我的是");
		 * 
		 * HttpClientUtil util = HttpClientUtil.getInstance("GBK");
		 * 
		 * String resultStr = util.getResponseBodyAsString(url,params); byte[]
		 * resultArr = util.getResponseBodyAsByteArray(url,params);
		 * 
		 * File file = new File("D:\\result.txt"); FileOutputStream out = new
		 * FileOutputStream(file);
		 * 
		 * util.getResponseBodyAsStream(url,params,out);
		 * 
		 * System.out.println("HttpClientUtil.main()-result:"+resultStr);
		 * if(resultArr != null){
		 * System.out.println("HttpClientUtil.main()-result:"+new
		 * String(resultArr)); }
		 */}
}